﻿using JNPF.Extensions;
using System.Dynamic;

namespace JNPF.ViewEngine;

/// <summary>
/// 匿名类型包装器
/// </summary>
[SuppressSniffer]
public class AnonymousTypeWrapper : DynamicObject
{
    /// <summary>
    /// 匿名模型
    /// </summary>
    private readonly object model;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="model"></param>
    public AnonymousTypeWrapper(object model)
    {
        this.model = model;
    }

    /// <summary>
    /// 获取成员信息
    /// </summary>
    /// <param name="binder"></param>
    /// <param name="result"></param>
    /// <returns></returns>
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var propertyInfo = model.GetType().GetProperty(binder.Name);

        if (propertyInfo == null)
        {
            result = null;
            return false;
        }

        result = propertyInfo.GetValue(model, null);

        if (result == null)
        {
            return true;
        }

        var type = result.GetType();

        if (result.IsAnonymous())
        {
            result = new AnonymousTypeWrapper(result);
        }

        var isEnumerable = typeof(IEnumerable).IsAssignableFrom(type);

        if (isEnumerable && result is not string)
        {
            result = ((IEnumerable<object>)result)
                    .Select(e =>
                    {
                        if (e.IsAnonymous())
                        {
                            return new AnonymousTypeWrapper(e);
                        }

                        return e;
                    })
                    .ToList();
        }

        return true;
    }
}